package cate.game.event.championrace;

import cate.game.GameBody;
import cate.game.framework.advanced.AdvancedTimerEvent;
import cate.game.pvp.championrace.data.ChampionRaceSpec;
import cate.game.pvp.championrace.timer.ChampionRaceTimerTask;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteClass;
import easy.java.time.DateTool;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Transient;

import java.util.StringJoiner;

@NoteClass(value = "精英赛事件类型")
@Data
public class ChampionRaceTimerEvent implements AdvancedTimerEvent {

    @Transient
    @JsonIgnore
    private GameBody gameBody;

    @FunctionalInterface
    public interface Creator {
        ChampionRaceTimerEvent createTimerEvent(ChampionRaceTimerTask.Setting settings);
    }

    public interface Handler {
        default void onOpenEvent(OpenEvent openEvent) {
        }

        default void onRankSettleEvent(RankSettleEvent rankSettleEvent) {
        }

        default void onInvitationEvent(InvitationEvent invitationEvent) {
        }

        default void onTrialEvent(TrialEvent trialEvent) {
        }

        default void onKoEvent(KoEvent koEvent) {
        }

        default void onFinalEvent(FinalEvent finalEvent) {
        }

        default void onRankSwitchEvent(RankSwitchEvent rankSwitchEvent) {
        }

        default void onShowEvent(ShowEvent showEvent) {
        }

        default void onRestEvent(RestEvent restEvent) {
        }
    }

    public enum EventType {
        /** */
        OPEN(1),
        /** */
        CLOSE(2),
        /** */
        SWITCH(3),
        /** */
        RANK_SETTLE(4),
        /** */
        INVITATION(5),
        /** */
        TRIAL_GROUP(6),
        /** */
        TRIAL(6),
        /** */
        KO_GROUP(25),
        /** */
        KO(25),
        /** */
        FINAL_GROUP(35),
        /** */
        FINAL(35),
        /** */
        RANK_SWITCH(45),
        /** */
        SHOW(46),
        /** */
        REST(47);

        @Getter
        final int flag;

        EventType(int flag) {
            this.flag = flag;
        }
    }

    private long executedTime = System.currentTimeMillis();
    private int season;
    private EventType eventType = EventType.OPEN;
    private OpenEvent openEvent;
    private ClosedEvent closedEvent;
    private SwitchEvent switchEvent;
    private RankSettleEvent rankSettleEvent;
    private InvitationEvent invitationEvent;
    private TrialGroupEvent trialGroupEvent;
    private TrialEvent trialEvent;
    private KoGroupEvent koGroupEvent;
    private KoEvent koEvent;
    private FinalGroupEvent finalGroupEvent;
    private FinalEvent finalEvent;
    private RankSwitchEvent rankSwitchEvent;
    private ShowEvent showEvent;
    private RestEvent restEvent;

    @Data
    public static class OpenEvent {
        private ChampionRaceSpec spec;
        private long openTime;
        private long closedTime;
        private int season;

        @Override
        public String toString() {
            return new StringJoiner(", ", OpenEvent.class.getSimpleName() + "[", "]")
                    .add("openTime=" + DateTool.instance().format(openTime))
                    .add("closedTime=" + DateTool.instance().format(closedTime))
                    .add("season=" + season)
                    .toString();
        }
    }

    @Data
    public static class ClosedEvent {
        private ChampionRaceSpec spec;
        private long closedTime = System.currentTimeMillis();

        @Override
        public String toString() {
            return new StringJoiner(", ", ClosedEvent.class.getSimpleName() + "[", "]")
                    .add("closedTime=" + DateTool.instance().format(closedTime))
                    .toString();
        }
    }

    @Data
    public static class SwitchEvent {
        private ChampionRaceSpec spec;
        private long switchTime = System.currentTimeMillis();
        private int fromSeason;
        private int toSeason;

        @Override
        public String toString() {
            return new StringJoiner(", ", SwitchEvent.class.getSimpleName() + "[", "]")
                    .add("switchTime=" + DateTool.instance().format(switchTime))
                    .add("fromSeason=" + fromSeason)
                    .add("toSeason=" + toSeason)
                    .toString();
        }
    }

    @NoArgsConstructor
    @Data
    public static class RankSettleEvent {
        private ChampionRaceSpec spec;
    }

    @Data
    public static class InvitationEvent {
        private ChampionRaceSpec spec;
    }

    @NoArgsConstructor
    @Data
    public static class TrialGroupEvent {
        private ChampionRaceSpec spec;
    }

    @Data
    public static class TrialEvent {
        private ChampionRaceSpec spec;
    }

    @Data
    public static class KoGroupEvent {
        private ChampionRaceSpec spec;
    }

    @Data
    public static class KoEvent {
        private ChampionRaceSpec spec;
    }

    @Data
    public static class FinalGroupEvent {
        private ChampionRaceSpec spec;
    }

    @Data
    public static class FinalEvent {
        private ChampionRaceSpec spec;
    }

    @Data
    public static class RankSwitchEvent {
        private ChampionRaceSpec spec;
    }

    @Data
    public static class ShowEvent {
        private ChampionRaceSpec spec;
    }

    @Data
    public static class RestEvent {
        private ChampionRaceSpec spec;
    }

    @Override
    public String toString() {
        StringJoiner stringJoiner = new StringJoiner(", ", ChampionRaceTimerEvent.class.getSimpleName() + "[", "]")
                .add("executedTime=" + DateTool.instance().format(executedTime));
        switch (eventType) {
            case OPEN:
                stringJoiner.add("openEvent=" + openEvent);
                break;
            case CLOSE:
                stringJoiner.add("closedEvent=" + closedEvent);
                break;
            case SWITCH:
                stringJoiner.add("switchEvent=" + switchEvent);
                break;
            case RANK_SETTLE:
                stringJoiner.add("rankSettleEvent=" + rankSettleEvent);
                break;
            case INVITATION:
                stringJoiner.add("invitationEvent=" + invitationEvent);
                break;
            case TRIAL_GROUP:
                stringJoiner.add("trialGroupEvent=" + trialGroupEvent);
                break;
            case TRIAL:
                stringJoiner.add("trialEvent=" + trialEvent);
                break;
            case KO_GROUP:
                stringJoiner.add("koGroupEvent=" + koGroupEvent);
                break;
            case KO:
                stringJoiner.add("koEvent=" + koEvent);
                break;
            case FINAL_GROUP:
                stringJoiner.add("finalGroupEvent=" + finalGroupEvent);
                break;
            case FINAL:
                stringJoiner.add("finalEvent=" + finalEvent);
                break;
            case RANK_SWITCH:
                stringJoiner.add("rankSwitchEvent=" + rankSwitchEvent);
                break;
            case SHOW:
                stringJoiner.add("showEvent=" + showEvent);
                break;
            case REST:
                stringJoiner.add("restEvent=" + restEvent);
                break;
            default:
                break;
        }
        return stringJoiner.toString();
    }
}
